package com.local.hwcard;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;


public class VoiceService extends Service {
    private static final String TAG = "VoiceService";
    private static final String CHANNEL_ID = "VoiceServiceChannelHWCard"; // 唯一渠道ID
    private static final int NOTIFICATION_ID = 1001; // 确保为正数
    private static final int CONNECT_TIMEOUT = 60;
    // 音频参数
    private static final int SAMPLE_RATE = 16000;
    private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;
    private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
    private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(
            SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT) * 2;
            
    private static VoiceService instance;
    private Callback callback;
    private final IBinder binder = new LocalBinder();
    private DatagramSocket socket;
    private InetAddress serverAddress;
    private int serverPort;

    private String asyncSendMessage = "";

    private AudioRecord audioRecord;
    private AudioTrack audioTrack;
    private boolean isRecording = false;
    private boolean isRunning = false;
    private Thread receiveThread;
	private Thread heartbeatThread;
    private Thread sendThread;
    private Handler mainHandler;

    private float[] echoLastOutput = new float[128];
    private float[] echoLastInput = new float[128];
    private float[] hpFilterLastValues = new float[2];
    
    // 回调接口
    public interface Callback {
        void onConnect(String message);
        void onConnectFail(String errorMsg);
        void onInitGame(String message);
        void onOtherJoin(String message);
        void onAck(String message);
        void onSync(String message);
        void onGiveup(String message);
    }

    public void setCallback(Callback callback) {
        this.callback = callback;
    }

    public static VoiceService getInstance() {
        return instance;
    }

    public class LocalBinder extends Binder {
        VoiceService getService() {
            return VoiceService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
		receiveThread = null;
		heartbeatThread = null;
        mainHandler = new Handler(Looper.getMainLooper());

        try {
            serverAddress = InetAddress.getByName(DeviceInfor.getServerIp());
            serverPort = DeviceInfor.getServerPort();

            // 1. 优先创建通知渠道
            boolean channelCreated = createNotificationChannel();
            if (!channelCreated && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // 渠道创建失败时的错误处理
                Log.e(TAG, "Notification channel creation failed");
                notifyConnectFail("Service initialization error");
                stopSelf();
                return;
            }

            // 2. 创建通知
            Notification notification = createNotification();
            if (notification == null) {
                Log.e(TAG, "Notification creation failed");
                notifyConnectFail("Service initialization error");
                stopSelf();
                return;
            }

            // 3. 启动前台服务（添加异常捕获）
            startForeground(NOTIFICATION_ID, notification);
            Log.d(TAG, "startForeground completed successfully");

            // 4. 初始化其他组件
            initAudioTrack();
        } catch (Exception e) {
            Log.e(TAG, "onCreate crash: " + e.getMessage(), e);
            notifyConnectFail("Service start failed: " + e.getMessage());
            stopSelf();
            return;
        }
    }

    // 确保通知渠道创建成功
    private boolean createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            try {
                CharSequence name = "Voice Conference";
                String description = "Used for voice communication";
                int importance = NotificationManager.IMPORTANCE_DEFAULT;

                NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
                channel.setDescription(description);
                channel.setSound(null, null); // 无提示音
                channel.setShowBadge(false); // 不显示徽章

                NotificationManager notificationManager = getSystemService(NotificationManager.class);
                if (notificationManager == null) {
                    Log.e(TAG, "NotificationManager is null");
                    return false;
                }

                notificationManager.createNotificationChannel(channel);
                // 验证渠道是否真的创建成功
                NotificationChannel createdChannel = notificationManager.getNotificationChannel(CHANNEL_ID);
                boolean success = createdChannel != null;
                Log.d(TAG, "Notification channel created: " + success);
                return success;
            } catch (Exception e) {
                Log.e(TAG, "createNotificationChannel error: " + e.getMessage(), e);
                return false;
            }
        }
        // 低版本不需要渠道，视为创建成功
        return true;
    }

    // 确保通知有效
    private Notification createNotification() {
        try {
            Intent intent = new Intent(this, MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

            // 适配不同Android版本的PendingIntent标志
            int flags = PendingIntent.FLAG_UPDATE_CURRENT;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                flags |= PendingIntent.FLAG_IMMUTABLE;
            }

            PendingIntent pendingIntent = PendingIntent.getActivity(
                    this, 0, intent, flags);

            Notification.Builder builder;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // 8.0+必须指定渠道ID
                builder = new Notification.Builder(this, CHANNEL_ID);
            } else {
                builder = new Notification.Builder(this);
                builder.setPriority(Notification.PRIORITY_DEFAULT);
            }

            // 必须设置小图标（使用系统默认图标避免资源问题）
            int smallIcon = android.R.drawable.stat_sys_phone_call;

            builder.setContentTitle(DeviceInfor.getAppName())
                    .setContentText("游戏中..")
                    .setSmallIcon(smallIcon)
                    .setContentIntent(pendingIntent)
                    .setOngoing(true) // 防止用户关闭
                    .setDefaults(Notification.DEFAULT_LIGHTS); // 只亮灯，无声音震动

            return builder.build();
        } catch (Exception e) {
            Log.e(TAG, "createNotification error: " + e.getMessage(), e);
            return null;
        }
    }

    // 连接服务器逻辑
    public void connectToServer() {
        new Thread(() -> {
            try {
                if (socket == null) {
                    socket = new DatagramSocket();
                }

                isRunning = true;
                Log.d(TAG, "===============");
                        // 发送reload请求
                byte[] requestData = ("RELOAD:" + DeviceInfor.getLocalID()).getBytes();
                DatagramPacket requestPacket = new DatagramPacket(
                        requestData, requestData.length,
                        serverAddress, DeviceInfor.getServerPort()
                );
                socket.send(requestPacket);
                Log.d(TAG, "Connect request sent");

                // 等待响应
                //socket.setSoTimeout(CONNECT_TIMEOUT);
                byte[] responseBuffer = new byte[BUFFER_SIZE];
                DatagramPacket responsePacket = new DatagramPacket(responseBuffer, responseBuffer.length);
                socket.receive(responsePacket);
                String response = new String(responsePacket.getData(), 0, responsePacket.getLength());

                Log.d(TAG, "response:" + response);

                if (response.startsWith("GAME")) {
                    if (callback != null) {
                        callback.onInitGame(response);
                    }
                } else if (response.startsWith("CONNECT")) {
                    if (callback != null) {
                        callback.onConnect(response);
                    }
                }

                startHeartbeatThread();
                startReceiveThread();

            } catch (Exception e) {
                Log.e(TAG, "Connection failed: " + e.getMessage());
                notifyConnectFail("Connection failed: " + e.getMessage());
            }
        }).start();
    }

    public boolean sendMessage(String message) {
        if (asyncSendMessage.isEmpty()) {
            asyncSendMessage = message;
            return true;
        } else {
            return false;
        }
    }

    private void startHeartbeatThread() {
        heartbeatThread = new Thread(() -> {
            String deviceId = DeviceInfor.getLocalID();
			byte[] requestData = ("HEARTBEAT:" + deviceId).getBytes();
			DatagramPacket requestPacket = new DatagramPacket(
					requestData, requestData.length,
					serverAddress, serverPort
			);

            int count = 0;
            while (isRunning && !Thread.currentThread().isInterrupted()) {
                try {
                    if (socket == null) {
                        break;
                    }
                    Thread.sleep(20);

                    count += 20;

                    if (count > 6000) {
                        // 6秒发送一次心跳
                        count = 0;
                        socket.send(requestPacket);
                    }

                    if (!asyncSendMessage.isEmpty()) {
                        // 异步发送消息
                        String message = asyncSendMessage;
                        asyncSendMessage = "";
                        byte[] messageData = message.getBytes();
                        DatagramPacket messagePacket = new DatagramPacket(
                                messageData, messageData.length,
                                serverAddress, serverPort
                        );
                        socket.send(messagePacket);
                    }

                    if (!deviceId.equals(DeviceInfor.getLocalID())) {
                        //修改名称
                        deviceId = DeviceInfor.getLocalID();
                        requestData = ("HEARTBEAT:" + deviceId).getBytes();
                        requestPacket = new DatagramPacket(
                                requestData, requestData.length,
                                serverAddress, serverPort
                        );

                        //发送重新加载消息
                        byte[] messageData = ("RELOAD:" + deviceId).getBytes();
                        DatagramPacket messagePacket = new DatagramPacket(
                                messageData, messageData.length,
                                serverAddress, serverPort
                        );
                        socket.send(messagePacket);
                    }

                } catch (Exception e) {
                    if (!Thread.currentThread().isInterrupted()) {
                        Log.e(TAG, "Heartbeat error: " + e.getMessage());
                    }
                }
            }
        });
        heartbeatThread.start();
    }

    private void startReceiveThread() {
        receiveThread = new Thread(() -> {
            byte[] buffer = new byte[BUFFER_SIZE];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

            while (isRunning && !Thread.currentThread().isInterrupted()) {
                try {
                    if (socket == null) {
                        break;
                    }
                    socket.receive(packet);

                    String response = new String(packet.getData(), 0, packet.getLength());
                    if (response.startsWith("GAME")) {
                        if (callback != null) {
                            callback.onInitGame(response);
                        }
                        continue;
                    }
                    if (response.startsWith("CONNECT")) {
                        if (callback != null) {
                            callback.onConnect(response);
                        }
                    }
                    if (response.startsWith("JOIN")) {
                        if (callback != null) {
                            callback.onOtherJoin(response);
                        }
                        continue;
                    }
                    if (response.startsWith("ACK")) {
                        if (callback != null) {
                            callback.onAck(response);
                        }
                        continue;
                    }
                    if (response.startsWith("SYNC")) {
                        if (callback != null) {
                            callback.onSync(response);
                        }
                        continue;
                    }
                    if (response.startsWith("GIVEUP")) {
                        if (callback != null) {
                            callback.onGiveup(response);
                        }
                        continue;
                    }

                    if (audioTrack != null) {
                        // 接收音频时应用高通滤波处理
                        byte[] filteredBuffer = highPassFilter(packet.getData(), packet.getLength(), hpFilterLastValues);
                        audioTrack.write(filteredBuffer, 0, packet.getLength());
						
						// 不用高通滤波，使用默认方式
						//audioTrack.write(packet.getData(), 0, packet.getLength());
                    }
                } catch (Exception e) {
                    if (!Thread.currentThread().isInterrupted()) {
                        Log.e(TAG, "Receive error2: " + e.getMessage());
                    }
                }
            }
        });
        receiveThread.start();
    }
	
	private void initAudioTrack() {
        try {
            int bufferSize = AudioTrack.getMinBufferSize(
                    SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AUDIO_FORMAT);

            audioTrack = new AudioTrack(
                    AudioManager.STREAM_VOICE_CALL,
                    SAMPLE_RATE,
                    AudioFormat.CHANNEL_OUT_MONO,
                    AUDIO_FORMAT,
                    bufferSize,
                    AudioTrack.MODE_STREAM
            );
            if (!DeviceInfor.getVolume().equals("1")) {
                try {
                    audioTrack.setVolume(Float.parseFloat(DeviceInfor.getVolume()));
                } catch (Exception exp) {
                    Log.e(TAG, "SetVolume failed: " + exp.getMessage());
                }
            }
            audioTrack.play();
        } catch (Exception e) {
            Log.e(TAG, "AudioTrack init failed: " + e.getMessage());
        }
    }

    public void startRecording() {
        if (isRecording) {
			return;
		}

        try {
            isRecording = true;
            audioRecord = new AudioRecord(
                    android.media.MediaRecorder.AudioSource.MIC,
                    SAMPLE_RATE,
                    CHANNEL_CONFIG,
                    AUDIO_FORMAT,
                    BUFFER_SIZE
            );

            if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
                throw new Exception("AudioRecord init failed");
            }

            audioRecord.startRecording();
            sendThread = new Thread(() -> {
                byte[] buffer = new byte[BUFFER_SIZE];
                while (isRecording) {
                    int bytesRead = audioRecord.read(buffer, 0, buffer.length);
                    if (bytesRead > 0 && socket != null) {
                        try {
                            // 发送音频前应用回声消除
                            //byte[] echoFiltered = eliminateEcho(buffer, bytesRead, echoLastOutput, echoLastInput);
                            //byte[] amplifiedBuffer = amplifyAudio(buffer, bytesRead, 10.0f);
                            socket.send(new DatagramPacket(
                                    buffer, bytesRead, serverAddress, serverPort));
                        } catch (Exception e) {
                            Log.e(TAG, "Send error: " + e.getMessage());
                        }
                    }
                }
            });
            sendThread.start();
        } catch (Exception e) {
            Log.e(TAG, "Start recording failed: " + e.getMessage());
            isRecording = false;
        }
    }

    // 放大声音
    private byte[] amplifyAudio(byte[] buffer, int length, float gain) {
        if (gain <= 1.0f) {
            return buffer;
        }

        // 转换为short数组进行处理（16位PCM格式）
        short[] shorts = new short[length / 2];
        ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(shorts);

        // 应用增益
        for (int i = 0; i < shorts.length; i++) {
            // 放大并防止溢出
            int amplified = (int) (shorts[i] * gain);
            if (amplified > Short.MAX_VALUE) {
                shorts[i] = Short.MAX_VALUE;
            } else if (amplified < Short.MIN_VALUE) {
                shorts[i] = Short.MIN_VALUE;
            } else {
                shorts[i] = (short) amplified;
            }
        }

        // 转换回byte数组
        ByteBuffer byteBuffer = ByteBuffer.allocate(length);
        byteBuffer.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(shorts);
        return byteBuffer.array();
    }
	
    // 回声消除处理
    private byte[] eliminateEcho(byte[] inputBuffer, int length, float[] lastOutput, float[] lastInput) {
        if (length <= 0) return inputBuffer;

        short[] inputShorts = new short[length / 2];
        ByteBuffer.wrap(inputBuffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(inputShorts);

        final float beta = 0.01f;
        int filterSize = Math.min(128, inputShorts.length);
        float[] filter = new float[filterSize];
        
        for (int i = 0; i < inputShorts.length; i++) {
            float echoEstimate = 0;
            for (int j = 0; j < filterSize && j <= i; j++) {
                int inputIndex = Math.max(0, i - j);
                echoEstimate += filter[j] * (inputIndex < lastOutput.length ? lastOutput[inputIndex] : 0);
            }
            
            int filtered = (int) (inputShorts[i] - echoEstimate);
            filtered = Math.max(Short.MIN_VALUE, Math.min(Short.MAX_VALUE, filtered));
            inputShorts[i] = (short) filtered;
            
            for (int j = 0; j < filterSize && j <= i; j++) {
                int inputIndex = Math.max(0, i - j);
                filter[j] += beta * filtered * (inputIndex < lastInput.length ? lastInput[inputIndex] : 0);
            }
        }
        
        ByteBuffer byteBuffer = ByteBuffer.allocate(length);
        byteBuffer.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(inputShorts);
        return byteBuffer.array();
    }

    // 高通滤波处理
    private byte[] highPassFilter(byte[] inputBuffer, int length, float[] lastValues) {
        if (length <= 0) return inputBuffer;

        final float alpha = 0.96f;
        
        short[] inputShorts = new short[length / 2];
        ByteBuffer.wrap(inputBuffer).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(inputShorts);
        
        for (int i = 0; i < inputShorts.length; i++) {
            if (i == 0 && lastValues != null && lastValues.length >= 2) {
                inputShorts[i] = (short) (inputShorts[i] - alpha * lastValues[0]);
            } else if (i > 0) {
                inputShorts[i] = (short) (inputShorts[i] - alpha * inputShorts[i - 1]);
            }
        }
        
        if (lastValues != null && lastValues.length >= 2) {
            lastValues[0] = inputShorts[inputShorts.length - 1];
        }
        
        ByteBuffer byteBuffer = ByteBuffer.allocate(length);
        byteBuffer.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(inputShorts);
        return byteBuffer.array();
    }


    public void stopRecording() {
        isRecording = false;
        if (sendThread != null) {
            sendThread.interrupt();
            sendThread = null;
        }
        if (audioRecord != null) {
            try {
                audioRecord.stop();
                audioRecord.release();
            } catch (Exception e) {
                Log.e(TAG, "Stop recording error: " + e.getMessage());
            }
            audioRecord = null;
        }
    }

    private void notifyConnectFail(String errorMsg) {
        mainHandler.post(() -> {
            if (callback != null) callback.onConnectFail(errorMsg);
            stopSelf();
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        isRunning = false;
        stopRecording();
        if (receiveThread != null) {
			receiveThread.interrupt();
		}
        if (heartbeatThread != null) {
			heartbeatThread.interrupt();
		}
        if (socket != null) {
			socket.close();
		}
        if (audioTrack != null) {
            audioTrack.stop();
            audioTrack.release();
        }
        instance = null;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }
}
